import re

from ninja.security import APIKeyHeader
from django.core.cache import cache

from models.models import User, ManagerUser, Api
from water_applets import settings

method_map = {
    'get': 0,
    'post': 1,
    'delete': 2,
    'put': 3,
}


class InvalidToken(Exception):
    pass


class InvalidPermission(Exception):
    pass


class AgentAuthBearer(APIKeyHeader):
    param_name = 'token'

    def authenticate(self, request, token):
        try:
            if token:
                if "::" not in token:
                    raise InvalidToken
                user_id, token = token.split("::")
                user = User.objects.get(pk=user_id)
                request.user = user
                key = settings.REDIS_AGENT_APPLETS_LOGIN_TOKEN_KEY.format(user_id=request.user.id)
                if cache.get(key) == token:
                    return user, token
            raise InvalidToken
        except:
            raise InvalidToken


class AppletAuthBearer(APIKeyHeader):
    param_name = 'token'

    def authenticate(self, request, token):
        try:
            if token:
                if "::" not in token:
                    raise InvalidToken
                user_id, token = token.split("::")
                user = User.objects.get(pk=user_id)
                request.user = user
                key = settings.REDIS_APPLETS_LOGIN_TOKEN_KEY.format(user_id=request.user.id)
                if cache.get(key) == token:
                    return user, token
            raise InvalidToken
        except:
            raise InvalidToken


class ManagerAuthBearer(APIKeyHeader):
    param_name = 'token'

    def authenticate(self, request, token):
        try:
            if token:
                if "::" not in token:
                    raise InvalidToken
                user_id, token = token.split("::")
                user = ManagerUser.objects.get(pk=user_id)
                request.user = user
                key = settings.REDIS_MANAGER_LOGIN_TOKEN_KEY.format(user_id=request.user.id)
                if cache.get(key) == token:
                    if not user.is_super:
                        try:
                            url_path = request.path_info
                            method = method_map.get(request.method.lower(), 0)
                            email_re = re.compile(r'(\d+)$')
                            if email_re.search(url_path):
                                position = '/'.join(url_path.split('/')[:-1]) + "/"
                                api = Api.objects.get(position__contains=position, method=method)
                            else:
                                api = Api.objects.get(position=url_path, method=method)
                            request.user.permission_group.api.get(id=api.id)
                        except:
                            raise InvalidPermission
                    return user, token
                raise InvalidToken
            raise InvalidToken
        except Exception as e:
            raise e
